package gui;

import java.awt.CardLayout;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;

import application.Aesp;
import application.EstimationUnit;

public class GUI extends JFrame implements ActionListener{
	protected Aesp aesp;
	protected String fileName;
	protected JTextField filePath;
	protected JLabel fileLabel;
	protected ArrayList<JTextField> textFields1;
	protected ArrayList<JTextField> textFields2;
	protected ArrayList<JComboBox> comboBoxes;
	protected JButton calcEffortButton;
	protected JLabel effort;
	protected int estUnit = 1;
	protected String[] characteristics;
	protected String[] charsNames;
	protected boolean noEmptyInput;
	protected boolean projectsImported;
	protected boolean hasData;
	protected int nbrOfComboboxes;
	protected int nbrOfTextFields;
	protected JPanel card1;
	protected JPanel card2;
	protected JPanel topPanel;
	protected CardLayout cl;

	public GUI(Aesp aesp) {
		super("Analogy-Based Effort Estimation");
		try {
			// Set System L&F
			UIManager.setLookAndFeel(
					UIManager.getSystemLookAndFeelClassName());
		} 
		catch (Exception e){
			System.err.println("Could not set the system look and feel");
		}
		this.aesp = aesp;
		charsNames = new String[aesp.getCharsNames().length-1];
		for (int i = 0; i < charsNames.length; i++) {
			charsNames[i] = aesp.getCharsNames()[i];
		}
	}


	public void setEstUnit(int i) {
		estUnit = i;
	}	

	public int getEstUnit() {
		return estUnit;
	}

	public void initGUI() {
		/*
		 * Menu at top
		 */
		addMenuBar();

		setLayout(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();

		/*
		 * Top panel with new project variables
		 */
		topPanel = new JPanel();
		// content newProjectPanel -->
		cl = new CardLayout();
		topPanel.setLayout(cl);
		Border border = new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), "New Project");
		topPanel.setBorder(border);
		addNewProjectPanel(topPanel);
		// <--
		c.gridy = 1;
		c.gridx = 1;
		c.fill = GridBagConstraints.HORIZONTAL;
		c.insets = new Insets(2, 2, 2, 2);
		add(topPanel, c);

		/*
		 * Middle panel with imported projects
		 */
		JPanel middlePanel = new JPanel();
		// content importedProjectsPanel -->
		JButton importButton = new JButton("Import projects");
		importButton.setEnabled(true);
		importButton.addActionListener(importListener());
		middlePanel.add(importButton);
		middlePanel.setBorder(BorderFactory.createTitledBorder(
				new EtchedBorder(EtchedBorder.LOWERED), "Imported Projects"));
		fileLabel = new JLabel("File:");
		fileLabel.setEnabled(false);
		middlePanel.add(fileLabel);
		filePath = new JTextField("", 20);
		filePath.setEditable(false);
		filePath.setEnabled(false);
		middlePanel.add(filePath);
		JButton viewFileButton = new JButton("View file data");
		viewFileButton.addActionListener(openTableListener());
		middlePanel.add(viewFileButton);
		// <--
		c.gridy = 2;
		add(middlePanel, c);

		/*
		 * Lower panel with effort calculation
		 */
		JPanel bottomPanel = new JPanel();
		// content calcEffortPanel-->
		bottomPanel.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED));
		calcEffortButton = new JButton("Calculate effort");
		calcEffortButton.setEnabled(false);
		calcEffortButton.addActionListener(new CalcEffortListener(this));
		bottomPanel.add(calcEffortButton);
		effort = new JLabel("Effort:");
		effort.setEnabled(false);
		bottomPanel.add(effort);
		// <--
		c.gridy = 3;
		add(bottomPanel, c);

		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		pack();
		setLocationRelativeTo(null);
		setVisible(true);
		setResizable(false);
	}

	protected ActionListener importListener() {
		ActionListener a = new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				String curDir = System.getProperty("user.dir")+"/data/";
				JFileChooser fc = new JFileChooser(curDir);
				fc.setDialogTitle("Import a projects file");
				int returnValue = fc.showOpenDialog(null);
				if (returnValue == JFileChooser.APPROVE_OPTION) {
					File file = fc.getSelectedFile();
					fileName = file.getPath();
					filePath.setText(fileName);
					filePath.setEnabled(true);
					fileLabel.setEnabled(true);
					projectsImported = true;
					if (noEmptyInput) {
						calcEffortButton.setEnabled(true);
						effort.setEnabled(true);
					}
					hasData = true;
					try {
						aesp.readFromFile(file);
					} catch (Exception e1) {
						JOptionPane.showMessageDialog(null,"Unsupported file");
						aesp.clear();
					}
					if (aesp.size() <= 0) {
						projectsImported = false;
						calcEffortButton.setEnabled(false);
					}
				}
			}
		};
		return a;
	}

	
	/**
	 * ActionListener for the view file data button 
	 */
	protected ActionListener openTableListener() {
		ActionListener a = new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				JFrame tableWindow = new ProjectEffortsTable(aesp, hasData);
			}
		};
		return a;
	}

	protected EstimationUnit getEstimationUnit(int eST_UNIT) {
		if (estUnit == 1) {
			return EstimationUnit.PERSON_HOURS;
		} else if (estUnit == 2) {
			return EstimationUnit.PERSON_DAYS;
		} else if (estUnit == 3) {
			return EstimationUnit.PERSON_MONTHS;
		} else {
			return EstimationUnit.PERSON_YEARS;
		}
	}

	/**
	 * Sets up the new project panel
	 */
	protected void addNewProjectPanel(JPanel p) {
		characteristics = new String[charsNames.length];
		card1 = new JPanel();
		card2 = new JPanel();
		card1.setLayout(new GridBagLayout());
		card2.setLayout(new GridBagLayout());

		nbrOfComboboxes = aesp.getCharsData().length;
		nbrOfTextFields = charsNames.length - nbrOfComboboxes;

		GridBagConstraints cLabels = new GridBagConstraints();
		GridBagConstraints cInputs = new GridBagConstraints();
		cLabels.insets = new Insets(4, 2, 4, 0);
		cInputs.insets = new Insets(2, 2, 2, 6);
		textFields1 = new ArrayList<JTextField>();
		textFields2 = new ArrayList<JTextField>();
		comboBoxes = new ArrayList<JComboBox>();
		int xPos1 = 1;
		int xPos2 = 2;
		int countLabels = 1;
		int countInputFields = 0;
		InputChecker ic = new InputChecker();
		for (int i = 0; i < 4; i++) {
			cLabels.gridx = xPos1;
			cInputs.gridx = xPos2;
			for (int j = 0; j < 5; j++) {
				String s = "";
				if (countLabels < 10) {
					s = s + "0"+countLabels+". ";
				} else {
					s = s +countLabels+". ";
				}
				if (countInputFields < charsNames.length) {

					s = s + charsNames[countInputFields];
				} else {
					s = s + "-";
				}
				countLabels++;
				cLabels.anchor = GridBagConstraints.BASELINE_LEADING;
				cLabels.gridy = j+1;
				cInputs.gridy = j+1;
				JLabel l1 = new JLabel(s);
				JLabel l2 = new JLabel(s);
				card1.add(l1, cLabels);
				card2.add(l2, cLabels);
				if (countInputFields < charsNames.length) {
					if (countInputFields < nbrOfComboboxes) {
						String[] effMults = ic.getEffMult(countInputFields, aesp);
						JComboBox cb = new JComboBox(effMults);
						cb.setEnabled(true);
						comboBoxes.add(cb);
						card2.add(cb,cInputs);

						JTextField tf = new JTextField("", 8);
						tf.setBackground(Color.WHITE);
						tf.setOpaque(false);
						tf.setBorder(BorderFactory.createLoweredBevelBorder());
						tf.setEditable(false);
						card1.add(tf,cInputs);
						tf.setEnabled(true);
						textFields1.add(tf);
					} else {
						JTextField tf1 = new JTextField("", 8);
						tf1.setBackground(Color.WHITE);
						tf1.setOpaque(false);
						tf1.setBorder(BorderFactory.createLoweredBevelBorder());
						tf1.setEditable(false);
						card1.add(tf1,cInputs);
						tf1.setEnabled(true);
						textFields1.add(tf1);

						JTextField tf2 = new JTextField("", 8);
						tf2.setBackground(Color.WHITE);
						tf2.setOpaque(false);
						tf2.setBorder(BorderFactory.createLoweredBevelBorder());
						tf2.setEditable(true);
						card2.add(tf2,cInputs);
						tf2.setEnabled(true);
						textFields2.add(tf2);
					}
					countInputFields++;

				} else {
					JTextField tf1 = new JTextField("", 8);
					tf1.setEditable(false);
					tf1.setEnabled(false);
					card1.add(tf1, cInputs);

					JTextField tf2 = new JTextField("", 8);
					tf2.setEditable(false);
					tf2.setEnabled(false);
					card2.add(tf2, cInputs);
				}
			}
			xPos1 = xPos1+2;
			xPos2 = xPos2+2;
		}
		JButton editButton1 = new JButton("Edit");
		JButton editButton2 = new JButton("Edit");
		JButton doneButton1 = new JButton("Done");
		JButton doneButton2 = new JButton("Done");
		editButton1.addActionListener(topButtonsListener(1));
		editButton1.setEnabled(true);
		editButton2.setEnabled(false);
		doneButton2.addActionListener(topButtonsListener(2));
		doneButton1.setEnabled(false);
		doneButton2.setEnabled(true);
		cLabels.gridy = 6;
		cLabels.gridx = 3;
		cLabels.gridwidth = 2;
		card1.add(editButton1, cLabels);
		card2.add(editButton2, cLabels);
		cLabels.gridx = 5;
		card1.add(doneButton1, cLabels);
		card2.add(doneButton2, cLabels);
		p.add(card1, "1");
		p.add(card2, "2");
	}

	/**
	 * ActionListener for the top panel buttons 
	 */
	protected ActionListener topButtonsListener(final int i) {
		ActionListener al = new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				/*
				 * edit button card1
				 */
				if (i == 1) {
					int index = textFields1.size() - textFields2.size();
					for (int i = 0; i < textFields2.size(); i++) {
						if (textFields1.get(index).getText().equalsIgnoreCase("#no input") ||
								textFields1.get(index).getText().equalsIgnoreCase("#input err")) {
							textFields2.get(i).setText("");
						}
						index++;
					}
					cl.show(topPanel, "2");
					repaint();
					/*
					 * done button card2
					 */
				} else if (i == 2) {
					noEmptyInput = true;
					int index = 0;
					for (int i = 0; i < nbrOfComboboxes; i++) {
						String s = (String) comboBoxes.get(i).getSelectedItem();
						if (s.equalsIgnoreCase("")) {
							noEmptyInput = false;
							// TODO - göra texten röd
							textFields1.get(index).setText("#no input");
							textFields1.get(index).setForeground(Color.RED);
						} else {
							characteristics[index] = s;
							textFields1.get(index).setText(s);
							textFields1.get(index).setForeground(Color.BLACK);
						}
						index++;
					}
					for (int i = 0; i < nbrOfTextFields; i++) {
						String s = textFields2.get(i).getText();
						if (s.equalsIgnoreCase("")) {
							// TODO - göra texten röd
							textFields1.get(index).setText("#no input");
							textFields1.get(index).setForeground(Color.RED);
							noEmptyInput = false;
						} else {
							try {
								Double d = Double.parseDouble(s);
								if (d < 0) {
									noEmptyInput = false;
									textFields1.get(index).setText("#input err");
									textFields1.get(index).setForeground(Color.RED);
								} else {
									textFields1.get(index).setText(d.toString());
									characteristics[index] = d.toString();
									textFields1.get(index).setForeground(Color.BLACK);
								}
							} catch (NumberFormatException e2) {
								noEmptyInput = false;
								// TODO - göra texten röd
								textFields1.get(index).setText("#input err");
								textFields1.get(index).setForeground(Color.RED);
							}
						}
						index++;
					}

					if (noEmptyInput && projectsImported) {
						calcEffortButton.setEnabled(true);
						effort.setEnabled(true);
					} else if (calcEffortButton.isEnabled()){
						calcEffortButton.setEnabled(false);
						effort.setEnabled(false);
					}
					cl.show(topPanel, "1");
					repaint();
				}
			}
		};
		return al;
	}

	/**
	 * Sets up the menu bar
	 */
	protected void addMenuBar() {
		JMenuBar menuBar = new JMenuBar();
		JMenu menu1 = new JMenu("File");
		menu1.setMnemonic(KeyEvent.VK_F);
		JMenu menu2 = new JMenu("Preferences");
		menu2.setMnemonic(KeyEvent.VK_P);
		JMenuItem resetAll = new JMenuItem("Reset All", KeyEvent.VK_R);
		JMenuItem exit = new JMenuItem("Exit", KeyEvent.VK_X);
		JMenuItem options = new JMenuItem("Options", KeyEvent.VK_O);

		resetAll.addActionListener (
				new ActionListener() {
					public void actionPerformed(ActionEvent e) {
						calcEffortButton.setEnabled(false);
						projectsImported = false;
						noEmptyInput = false;
						fileName = "";
						fileLabel.setEnabled(false);
						filePath.setText(fileName);
						filePath.setEnabled(false);
						hasData = false;
						try {
							aesp.importCharData();
						} catch (IOException e1) {
							e1.printStackTrace();
						}
						charsNames = new String[aesp.getCharsNames().length-1];
						for (int i = 0; i < charsNames.length; i++) {
							charsNames[i] = aesp.getCharsNames()[i];
						}
						topPanel.removeAll();
						addNewProjectPanel(topPanel);
						pack();
						repaint();
					}
				}
				);

		
		

		options.addActionListener(this);

		exit.addActionListener (
				new ActionListener() {
					public void actionPerformed(ActionEvent e) {
						System.exit(0);
					}
				}
				);
		setJMenuBar(menuBar);
		menuBar.add(menu1);
		menuBar.add(menu2);
		menu1.add(resetAll);
		menu1.add(exit);
		menu2.add(options);
	}
	
	/**
	 * Recalculates the THRESHOLD as a whole percentage
	 */
	protected int thresholdAsWholePercentage() {
		return aesp.getThreshold();
	}


	@Override
	public void actionPerformed(ActionEvent arg0) {
		OptionsWindow ow = new OptionsWindow(this);
	}

}
